/*
	weak_type_allocator.hpp
	@author:Wolfhead
*/
#ifndef WOLV_WEAK_TYPE_ALLOCATOR_HPP
#define WOLV_WEAK_TYPE_ALLOCATOR_HPP

#include "weak_type_mempool.hpp"

#ifdef USE_STL_TRAITS
#	include <type_traits>
#endif

namespace wolv
{
namespace weakType
{
namespace allocator
{

namespace _detail
{
	template<typename T, bool trivail>
	struct _memRelease_traits;
}

/************************************************************************/
/*  Allocator                                                           */
/************************************************************************/
template<typename T>
class Allocator
{
public:
	static T * alloc();
	static T * alloc(const T& obj);
	static void release(T * pointer);
	static void * malloc(size_t size);
	static void free(void * pointer);

private:
	Allocator();
	Allocator(const Allocator&);
	Allocator& operator=(const Allocator&);
};


template<typename T>
T * Allocator<T>::alloc()
{
	return new(static_cast<T*>(MemPool<sizeof(T)>::Instance().alloc())) T();
}

template<typename T>
T * Allocator<T>::alloc(const T& obj)
{
	return new(static_cast<T*>(MemPool<sizeof(T)>::Instance().alloc())) T(obj);
}

template<typename T>
void Allocator<T>::release( T * pointer )
{
#ifdef USE_STL_TRAITS
	_memRelease_traits<T, std::has_trivial_destructor<T> >::release(pointer)
#else
	pointer->~T();
#endif
	return MemPool<sizeof(T)>::Instance().release(pointer);
}


template<typename T>
void * Allocator<T>::malloc( size_t size )
{
	return MemPool<sizeof(T)>::Instance().alloc();
}

template<typename T>
void Allocator<T>::free( void * pointer )
{
	return Allocator<T>::release(static_cast<T*>(pointer));
}


/************************************************************************/
/*  New Allocator                                                           */
/************************************************************************/
template<typename T>
class NewAllocator
{
public:
	static T * alloc();
	static T * alloc(const T& obj);
	static void release(T * pointer);
	static void * malloc(size_t size);
	static void free(void * pointer);

private:
	NewAllocator();
	NewAllocator(const NewAllocator&);
	NewAllocator& operator=(const NewAllocator&);
};


template<typename T>
T * NewAllocator<T>::alloc()
{
	return new T();
}

template<typename T>
T * NewAllocator<T>::alloc(const T& obj)
{
	return new T(obj);
}

template<typename T>
void NewAllocator<T>::release( T * pointer )
{
	delete pointer;
	return;
}


template<typename T>
void * NewAllocator<T>::malloc( size_t size )
{
	return new T();
}

template<typename T>
void NewAllocator<T>::free( void * pointer )
{
	delete (T*)pointer;
}




/************************************************************************/
/* Detail                                                               */
/************************************************************************/


namespace _detail
{
	template<typename T, bool trivail>
	struct _memRelease_traits{};

	template<typename T>
	struct _memRelease_traits<T, true>
	{
		static void release(T * pointer){};
	};

	template<typename T>
	struct _memRelease_traits<T, false>
	{
		static void release(T * pointer)
		{
			pointer->~T();
		};
	};
}

}//namespace allocator
}//namespace weakType
}//namespace wolv

#endif
